﻿using System.Reflection;
using Core.Infrastructure;

namespace Core.Helpers;

public static class AssemblyDiscoveryHelper
{
    /// <summary>
    /// 扫描主程序及插件目录下的所有 DLL 文件，并返回文件路径与版本号的集合。
    /// </summary>
    /// <param name="fileProvider">文件提供器（例如 IFileProvider 或自定义的 CommonHelper.DefaultFileProvider）</param>
    /// <param name="pluginFolderName">插件目录名称，默认 "Plugins"</param>
    /// <returns>包含 DLL 路径和版本号的列表</returns>
    public static List<KeyValuePair<string, Version>> GetAllAssemblies(IBoilerplateFileProvider fileProvider, string pluginFolderName = "Plugins")
    {
        var baseAppLibraries = new List<KeyValuePair<string, Version>>();
        var pluginLibraries = new List<KeyValuePair<string, Version>>();

        // ✅ 扫描 AppDomain 基目录下所有 dll
        foreach (var file in fileProvider.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll"))
            baseAppLibraries.Add(new KeyValuePair<string, Version>(file, GetAssemblyVersion(file)));

        // ✅ 如果当前目录不同于基目录，也扫描当前目录
        if (!AppDomain.CurrentDomain.BaseDirectory.Equals(Environment.CurrentDirectory, StringComparison.InvariantCultureIgnoreCase))
        {
            foreach (var file in fileProvider.GetFiles(Environment.CurrentDirectory, "*.dll"))
                baseAppLibraries.Add(new KeyValuePair<string, Version>(file, GetAssemblyVersion(file)));
        }

        // ✅ 扫描插件目录下的 dll
        var pluginsDir = new DirectoryInfo(fileProvider.Combine(Environment.CurrentDirectory, pluginFolderName));
        if (pluginsDir.Exists)
        {
            foreach (var subDir in pluginsDir.GetDirectories())
            {
                var pluginPathName = fileProvider.Combine(subDir.FullName);
                if (fileProvider.DirectoryExists(pluginPathName))
                {
                    foreach (var file in fileProvider.GetFiles(pluginPathName, "*.dll"))
                        pluginLibraries.Add(new KeyValuePair<string, Version>(file, GetAssemblyVersion(file)));
                }
            }
        }

        // ✅ 合并并去重
        var allLibraries = pluginLibraries.Concat(baseAppLibraries)
            .GroupBy(x => Path.GetFileName(x.Key), StringComparer.OrdinalIgnoreCase)
            .Select(g => g.First()) // 保留第一个
            .ToList();

        return allLibraries;
    }

    /// <summary>
    /// 获取程序集版本号
    /// </summary>
    private static Version GetAssemblyVersion(string filePath)
    {
        try
        {
            var assemblyName = AssemblyName.GetAssemblyName(filePath);
            return assemblyName.Version ?? new Version(1, 0, 0, 0);
        }
        catch
        {
            return new Version(1, 0, 0, 0);
        }
    }
}
